package com.shanzmoo.merchant.manage.api.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.shanzmoo.base.bean.PageRespBase;
import com.shanzmoo.base.bean.SResponse;
import com.shanzmoo.base.util.CollectionUtil;
import com.shanzmoo.core.domain.dto.SysUserSaveDTO;
import com.shanzmoo.core.domain.dto.SysUserUpdateDTO;
import com.shanzmoo.db.domain.dto.UserQueryDTO;
import com.shanzmoo.db.domain.vo.UserPageVo;
import com.shanzmoo.db.module.msys.entity.*;
import com.shanzmoo.db.module.msys.service.*;
import com.shanzmoo.db.module.psys.domain.vo.user.*;
import com.shanzmoo.merchant.manage.api.config.UserComponent;
import com.shanzmoo.merchant.manage.api.domain.AuthUser;
import com.shanzmoo.merchant.manage.api.util.BCryptUtils;
import com.shanzmoo.merchant.manage.api.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户管理
 *
 * @author： Gzhao 2021/3/28
 */
@Component
@RequiredArgsConstructor
public class SysUserManager {
    /**
     * 创建用户初始化登录密码
     */
    private static final String INIT_PASSWORD = "999999";

    private final IMSysUserService userService;
    private final IMSysUserRoleService userRoleService;
    private final IMSysRoleService roleService;
    private final IMSysMenuService menuService;
    private final IMSysRoleMenuService roleMenuService;
    private final UserComponent userComponent;

    public SResponse<Boolean> updatePassword(UserUpdatePasswordDto updateDto) {
        MSysUserEntity user = userService.getById(SecurityUtil.getCurrentUserId());

        MSysUserEntity updateUser = new MSysUserEntity();
        updateUser.setId(user.getId());
        updateUser.setPassword(BCryptUtils.encodePassword(updateDto.getPassword()));

        userService.updateById(updateUser);
        return SResponse.ok(Boolean.TRUE);
    }

    public SResponse<PageRespBase<UserPageVo>> getPageList(UserQueryDTO queryDto) {
        IPage<UserPageVo> page = userService.getPageList(queryDto);
        PageRespBase<UserPageVo> re = PageRespBase.create(page, page.getRecords());
        return SResponse.ok(re);
    }

    @Transactional(rollbackFor = Exception.class)
    public SResponse<Boolean> add(SysUserSaveDTO saveDTO) {
        MSysUserEntity entity = saveDTO.convertM();

        List<MSysUserEntity> checkList = userService.lambdaQuery()
                .eq(MSysUserEntity::getDeleted, false)
                .eq(MSysUserEntity::getUsername, entity.getUsername())
                .list();
        Assert.isTrue(CollUtil.isEmpty(checkList), "用户名已存在");

        entity.setCreateUser(userComponent.getUserId());
        entity.setMerchantCode(userComponent.getMerchantCode());
        entity.setPassword(BCryptUtils.encodePassword(INIT_PASSWORD));
        userService.save(entity);

        List<MSysUserRoleEntity> userRoleList = new ArrayList<>();
        saveDTO.getRoleIds().forEach(
                roleId -> {
                    userRoleList.add(SysUserSaveDTO.convertUserRoleM(entity.getId(), roleId));
                }
        );
        userRoleService.saveBatch(userRoleList);

        return SResponse.ok(Boolean.TRUE);
    }

    @Transactional(rollbackFor = Exception.class)
    public SResponse<Boolean> update(SysUserUpdateDTO updateDTO) {
        MSysUserEntity entity = updateDTO.convertM();

        List<MSysUserEntity> checkList = userService.lambdaQuery()
                .eq(MSysUserEntity::getDeleted, false)
                .eq(MSysUserEntity::getUsername, entity.getUsername())
                .ne(MSysUserEntity::getId, entity.getId())
                .list();
        Assert.isTrue(CollUtil.isEmpty(checkList), "用户名已存在");

        entity.setUpdateUser(userComponent.getUserId());
        userService.updateById(entity);

        userRoleService.deleteUserRole(entity.getId());

        List<MSysUserRoleEntity> userRoleList = new ArrayList<>();
        updateDTO.getRoleIds().forEach(
                roleId -> {
                    userRoleList.add(SysUserSaveDTO.convertUserRoleM(entity.getId(), roleId));
                }
        );
        userRoleService.saveBatch(userRoleList);

        return SResponse.ok(Boolean.TRUE);
    }

    public void statusChange(Integer id) {
        MSysUserEntity entity = userService.getById(id);
        Assert.isTrue(ObjectUtil.isNotNull(entity), "用户不存在");

        userService.lambdaUpdate()
                .eq(MSysUserEntity::getId, id)
                .set(MSysUserEntity::getStatus, !entity.getStatus())
                .update();
    }

    public void initPassword(Integer id) {
        userService.lambdaUpdate()
                .set(MSysUserEntity::getPassword, BCryptUtils.encodePassword(INIT_PASSWORD))
                .set(MSysUserEntity::getUpdateUser, userComponent.getUserId())
                .eq(MSysUserEntity::getId, id)
                .update();
    }

    public UserDetails findByUserName(String username) {
        MSysUserEntity user = userService.lambdaQuery().eq(MSysUserEntity::getUsername, username).one();
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        // 角色
        List<Integer> roleIds = userRoleService.lambdaQuery()
                .eq(MSysUserRoleEntity::getUserId, user.getId())
                .list()
                .stream()
                .map(MSysUserRoleEntity::getRoleId)
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(roleIds)) {
            return AuthUser.create(user, null, null);
        }
        List<MSysRoleEntity> roleList = roleService.lambdaQuery()
                .in(MSysRoleEntity::getId, roleIds)
                .eq(MSysRoleEntity::getDeleted, false)
                .list();
        if (CollUtil.isEmpty(roleList)) {
            return AuthUser.create(user, null, null);
        }
        // 权限
        List<Object> tmpMenuIds = roleMenuService.getBaseMapper().selectObjs(Wrappers
                .<MSysRoleMenuEntity>lambdaQuery()
                .in(MSysRoleMenuEntity::getRoleId, roleIds)
                .select(MSysRoleMenuEntity::getMenuId)
        );
        if (CollUtil.isEmpty(tmpMenuIds)) {
            return AuthUser.create(user, CollectionUtil.convert(roleIds, Integer.class), null);
        }
        List<MSysMenuEntity> menuList = menuService
                .lambdaQuery()
                .in(MSysMenuEntity::getMenuId, tmpMenuIds)
                .list();
        if (CollUtil.isEmpty(menuList)) {
            return AuthUser.create(user, CollectionUtil.convert(roleIds, Integer.class), null);
        }
        List<String> perms = menuList.stream()
                .map(MSysMenuEntity::getPerms)
                .filter(StrUtil::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());
        return AuthUser.create(user, CollectionUtil.convert(roleIds, Integer.class), perms);
    }
}
